package model.jgap;


import model.market.MarketInformation;

import org.jgap.*;
import org.jgap.impl.*;

public class PortfolioController {
  
  /**
   * The total number of times we'll let the population evolve.
   */
  private static final int MAX_ALLOWED_EVOLUTIONS = 10;
  

  public double[] balancePortfolio(MarketInformation info, double[] expectedExcessReturns, double[] guesses,double indexVariance,double[] assetNonSpecVariance)
      throws Exception {
	  Configuration.reset();
	Configuration conf = new DefaultConfiguration();
    conf.setPreservFittestIndividual(true);
    conf.setKeepPopulationSizeConstant(false);
    
    
    FitnessFunction myFunc =new PortfolioSharpeFitnessFunction(info,expectedExcessReturns,indexVariance,assetNonSpecVariance);

    //conf.setBulkFitnessFunction(new BulkFitnessOffsetRemover(myFunc));
    conf.setFitnessFunction(myFunc);
    
    Gene[] sampleGenes =  new Gene[info.getNumberOfAssets()];
    

	for(int i=0;i<info.getNumberOfAssets();i++){
    	sampleGenes[i]=new DoubleGene(conf,0,1);
    	if(guesses!=null){
    		sampleGenes[i].setAllele(guesses[i]);
    	}
    }
	
	
    IChromosome sampleChromosome = new Chromosome(conf, sampleGenes);
    conf.setSampleChromosome(sampleChromosome);
    conf.setPopulationSize((int)(Math.sqrt(info.getNumberOfAssets())*80));  
    Genotype population = Genotype.randomInitialGenotype(conf);
    if(guesses!=null){//AM: does this guess stuff actually change anything??
    	population.getPopulation().addChromosome(sampleChromosome);
    }
    
    // Evolve the population. Since we don't know what the best answer
    // is going to be, we just evolve the max number of times.
    // ---------------------------------------------------------------
    long startTime = System.currentTimeMillis();
    int evolveCount = 0;
    for (; evolveCount < MAX_ALLOWED_EVOLUTIONS;evolveCount++) {
 //   	System.out.println("At number: "+evolveCount+" population: "+population.getPopulation().size());
//    	List fittestChromosomes = population.getFittestChromosomes(10);
//    	for(int chromCount=1;chromCount<fittestChromosomes.size();chromCount++){
//    		if(fittestChromosomes.get(chromCount).equals(fittestChromosomes.get(chromCount-1))){
//    			System.out.println("summat fu*ked.");
//    		}
//    	}
    	population.evolve();
    }
    long endTime = System.currentTimeMillis();
//    System.out.println("Total evolution time: " + ( endTime - startTime)
//                       + " ms, evolutions "+evolveCount);
    
    IChromosome bestSolutionSoFar = population.getFittestChromosome();
    
//    System.out.println("The best solution has a fitness value of " +
//                       bestSolutionSoFar.getFitnessValue());
    Gene[] genes = bestSolutionSoFar.getGenes();
    double[] resultsArray= new double[genes.length];
    for(int i=0;i<genes.length;i++){
    	resultsArray[i]=(Double)(genes[i].getAllele());
    }
    //AM: convert results to sum to one..
    double totalPortfolio = 0;
    
    for(int i=0;i<resultsArray.length;i++){
    	totalPortfolio+=resultsArray[i];
    }
   
    double[] weightings= new double[info.getNumberOfAssets()];	
    for(int i=0;i<weightings.length;i++){
    	weightings[i]= resultsArray[i]/totalPortfolio;
    	
    }
    
    return weightings;
    
  }
  
}


